<template>
    <el-form ref="formRef" :style="style" :model="formModel" :label-width="formLabelWidth" :size="formSize" status-icon :rules="formRules">
        <el-form-item v-for="(item, index) in formItem" :key="index" :label="item.label" :prop="index" v-show="formIsShowEmpty || formModel[index]">
            <el-input v-if="item.type === 'input'" v-model="formModel[index]" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请输入${item.label}`" :maxlength="item.maxlength" :show-word-limit="item.showWordLimit" :clearable="item?.clearable ? item.clearable : true" :prefix-icon="item.prefixIcon" :suffix-icon="item.suffixIcon" :style="item.style" :readonly="item.readonly" :size="item.size" />
            <el-input v-else-if="item.type === 'password'" type="password" show-password v-model="formModel[index]" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请输入${item.label}`" :maxlength="item.maxlength" :show-word-limit="item.showWordLimit" :clearable="item?.clearable ? item.clearable : true" :prefix-icon="item.prefixIcon" :suffix-icon="item.suffixIcon" :style="item.style" :readonly="item.readonly" :size="item.size" />
            <el-input v-else-if="item.type === 'textarea'" type="textarea" :rows="item.rows" :autosize="item.autosize" v-model="formModel[index]" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请输入${item.label}`" :maxlength="item.maxlength" :show-word-limit="item.showWordLimit" :clearable="item?.clearable ? item.clearable : true" :prefix-icon="item.prefixIcon" :suffix-icon="item.suffixIcon" :style="item.style" :readonly="item.readonly" :size="item.size" />
            <el-input-number v-else-if="item.type === 'number'" v-model="formModel[index]" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请输入${item.label}`" :min="item.min" :max="item.max" :step="item.step" :clearable="item?.clearable ? item.clearable : true" :style="item.style" :readonly="item.readonly" :size="item.size" :controls-position="item.controlsPosition" />
            <el-input-tag v-else-if="item.type === 'tag'" v-model="formModel[index]" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请输入${item.label}`" :clearable="item?.clearable ? item.clearable : true" :style="item.style" :readonly="item.readonly" :size="item.size" />
            <el-radio-group v-else-if="item.type === 'radio'" v-model="formModel[index]" :size="item.size" :style="{ ...item.style, 'pointer-events': item.readonly ? 'none' : 'auto' }">
                <template v-if="item.button">
                    <el-radio-button v-for="(opt, ind) in item.options" :key="`${index}-${ind}`" :value="opt.value" :label="opt.label" :disabled="item.disabled" />
                </template>
                <template v-else>
                    <el-radio v-for="(opt, ind) in item.options" :key="`${index}-${ind}`" :value="opt.value" :disabled="item.disabled" :border="item.border" :size="item.size">{{ opt.label }}</el-radio>
                </template>
            </el-radio-group>
            <el-checkbox-group v-else-if="item.type === 'checkbox'" v-model="formModel[index]" :size="item.size" :style="{ ...item.style, 'pointer-events': item.readonly ? 'none' : 'auto' }">
                <el-checkbox v-for="(opt, ind) in item.options" :key="`${index}-${ind}`" :label="opt.label" :value="opt.value" :disabled="item.disabled" :border="item.border" :size="item.size" />
            </el-checkbox-group>
            <el-select v-else-if="item.type === 'select'" v-model="formModel[index]" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请选择${item.label}`" :size="item.size" :style="{ ...item.style, 'pointer-events': item.readonly ? 'none' : 'auto' }" :clearable="item?.clearable ? item.clearable : true" :multiple="item.multiple" :filterable="item.filterable">
                <el-option v-for="(opt, ind) in item.options" :key="`${index}-${ind}`" :label="opt.label" :value="opt.value" :disabled="opt?.disabled || false" />
            </el-select>
            <el-tree-select v-else-if="item.type === 'tree-select'" v-model="formModel[index]" :node-key="item?.nodeKey ? item.nodeKey : 'value'" :data="item?.options" :render-after-expand="item.renderAfterExpand" :check-strictly="item.checkStrictly" :show-checkbox="item.showCheckbox" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请选择${item.label}`" :size="item.size" :style="{ ...item.style, 'pointer-events': item.readonly ? 'none' : 'auto' }" :clearable="item?.clearable ? item.clearable : true" :multiple="item.multiple" :filterable="item.filterable" :default-expand-all="item.defaultExpandAll" />
            <el-switch v-else-if="item.type === 'switch'" v-model="formModel[index]" :active-text="item.activeText" :inactive-text="item.inactiveText" :inline-prompt="item.inlinePrompt" :active-value="item.activeValue" :inactive-value="item.inactiveValue" :active-icon="item.activeIcon" :inactive-icon="item.inactiveIcon" :style="{ ...item.style, 'pointer-events': item.readonly ? 'none' : 'auto' }" :size="item.size" class="switch-class" />
            <el-date-picker v-else-if="item.type === 'datetime'" v-model="formModel[index]" type="datetime" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请选择${item.label}`" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" :clearable="item?.clearable ? item.clearable : true" :style="{ ...item.style, width: '100%' }" :readonly="item.readonly" :size="item.size" />
            <el-date-picker v-else-if="item.type === 'timestamp'" v-model="formModel[index]" type="datetime" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请选择${item.label}`" format="YYYY-MM-DD HH:mm:ss" value-format="x" :clearable="item?.clearable ? item.clearable : true" :style="{ ...item.style, width: '100%' }" :readonly="item.readonly" :size="item.size" />
            <el-date-picker v-else-if="item.type === 'date'" v-model="formModel[index]" type="date" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请选择${item.label}`" format="YYYY-MM-DD" value-format="YYYY-MM-DD" :clearable="item?.clearable ? item.clearable : true" :style="{ ...item.style, width: '100%' }" :readonly="item.readonly" :size="item.size" />
            <el-time-picker v-else-if="item.type === 'time'" v-model="formModel[index]" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请选择${item.label}`" :style="{ ...item.style, width: '100%' }" :readonly="item.readonly" :size="item.size" :clearable="item?.clearable ? item.clearable : true" value-format="HH:mm:ss" format="HH:mm:ss" />
            <lemon-city v-else-if="item.type === 'city'" v-model:provinceId="formModel.provinceId" v-model:cityId="formModel.cityId" v-model:countyId="formModel.countyId" :rules="item.rules" :style="{ ...item.style, 'pointer-events': item.readonly ? 'none' : 'auto' }" />
            <lemon-image-upload v-else-if="item.type === 'image-upload'" v-model="formModel[index]" :uploadUrl="item.uploadUrl" :maxSize="item.maxSize" :style="{ ...item.style, 'pointer-events': item.readonly ? 'none' : 'auto' }" />
            <lemon-cascader v-else-if="item.type === 'cascader'" v-model="formModel[index]" :options="item.options" :cascaderProps="item.cascaderProps" :style="{ ...item.style, 'pointer-events': item.readonly ? 'none' : 'auto' }" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请选择${item.label}`"></lemon-cascader>
            <el-select v-else-if="item.type === 'icon'" v-model="formModel[index]" :placeholder="item.placeholder || item.readonly ? item.placeholder : `请选择${item.label}`" :clearable="item?.clearable ? item.clearable : true" :style="{ ...item.style, 'pointer-events': item.readonly ? 'none' : 'auto' }">
                <template #prefix v-if="formModel[index]">
                    <lemon-icon :icon="formModel[index]" style="float: left" :size="23" />
                </template>
                <el-option v-for="opt in icons" :key="opt.name" :value="opt?.name as any">
                    <lemon-icon :icon="opt?.name" style="float: left" :size="23" />
                    <span style="float: right">{{ opt.name }}</span>
                </el-option>
            </el-select>
        </el-form-item>
        <el-form-item v-if="formButton">
            <div class="form-btn" :style="{ marginRight: formLabelWidth }">
                <slot name="frontBtn"></slot>
                <el-button type="primary" @click="() => onSubmit(formRef)">提交</el-button>
                <slot name="centerBtn"></slot>
                <el-button @click="onCancel">取消</el-button>
                <slot name="afterBtn"></slot>
            </div>
        </el-form-item>
    </el-form>
</template>

<script setup lang="ts">
import { ref, nextTick, computed, watch } from "vue";
import type { ComponentSize, FormInstance, FormRules } from "element-plus";
import * as icons from "@element-plus/icons-vue";

//接收父类传过来的参数
interface Props {
    formModel: Record<string, any>;
    style?: Record<string, any>;
    formLabelWidth?: string;
    formSize?: ComponentSize;
    formItem?: Record<string, any>;
    formButton?: boolean;
    formIsShowEmpty?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
    formModel: () => ({}),
    style: () => ({}),
    formLabelWidth: "80px",
    formSize: "default",
    formItem: () => ({}),
    formButton: true,
    formIsShowEmpty: true, //是否显示空的表单项，默认展示
});

//表单验证规则
const formRules = computed<FormRules>(() => {
    return Object.entries(props.formItem).reduce((acc, [key, value]) => {
        // 如果当前字段有 rules，则添加到新对象中
        if (value.rules) {
            acc[key] = value.rules;
        } else {
            // 如果没有 rules，则设置为空数组
            acc[key] = [];
        }
        return acc;
    }, {} as Record<string, FormRules[]>);
});

//formModel中的timestamp类型转换成 Number类型
watch(
    props.formModel,
    (newValue: any, _oldValue: any) =>
        Object.entries(props.formItem)
            .filter(([_key, value]) => value.type === "timestamp")
            .filter(([key, _value]) => typeof newValue[key] === "string")
            .forEach(([key, _value]) => (props.formModel[key] = parseInt(newValue[key]))),
    { immediate: true, deep: false }
); //此处的deep配置不再奏效

//表单引用
const formRef = ref<FormInstance>();

//使用defineEmits注册一个自定义事件,子传父
const emit = defineEmits(["onSubmit", "onCancel"]);
//提交表单
const onSubmit = async (formEl: FormInstance | undefined) => {
    if (!formEl) return;
    await formEl.validate((valid: any, _fields: any) => {
        if (valid) {
            emit("onSubmit", props.formModel);
        }
    });
};

//取消表单
const onCancel = () => emit("onCancel");

//重置表单
const resetFields = () => nextTick(() => setTimeout(() => formRef.value?.resetFields(), 500));

//把方法暴露给父组件使用
defineExpose({
    formRef: () => formRef.value,
    resetFields: resetFields,
});
</script>

<style scoped lang="less">
.form-btn {
    text-align: center;
    width: 100%;
}
.switch-class {
    --el-switch-on-color: #13ce66;
    --el-switch-off-color: #ff4949;
}
</style>
